local profile = require "nmgprofile"
local cjson = require "cjson"

local profilerex = {
		funcstack = {},
		callList = {},
	}

local function genStackElement(info,st)
	return {
					st = st,
					src = info.short_src,
					dl = info.linedefined,
			}
end

local function getStackElementSt(sDt)
	assert(sDt)
	return sDt.st
end

local function hookLogic(...)
	local flag = ...
	local co = coroutine.running()
	local info = debug.getinfo(co,2)
	if info.what ~= 'C' then
		local stackT = profilerex.funcstack[co]
		local callL = profilerex.callList[co]
		if flag == "call" or flag == "tail call" then
			local st = profile.gettime()
			table.insert(stackT,genStackElement(info,st))
		elseif flag == "return" then
			local et = profile.gettime()
			local sDt = table.remove(stackT)
			local st = getStackElementSt(sDt)
			local ct = et - st
			table.insert(callL,{
					c = ct,
					l = (#stackT+1),
					src = info.short_src,
					ldefined = info.linedefined,
				})
		else
			error(tostring(flag))
		end
	end
end

function profilerex:start(co)
	assert(co)
	debug.sethook(co,hookLogic,"cr")
	self.funcstack[co] = {}
	self.callList[co] = {}
end

function profilerex:clear(co)
	debug.sethook(co)
	self.funcstack[co] = {}
	self.callList[co] = {}
end


function profilerex:getCallList(co)
	return self.callList[co]
end

function profilerex:getSelfCallList()
	local co = coroutine.running()
	return self:getCallList(co) or {}
end

return profilerex